/*
    SlideScript - minimalistic top-down scripting language.
    (C) Copyright 2014-2022 Chris Dorman - some rights reserved (GPLv2)

    View README file supplied with this software for more details
*/

#include "inc/deps.h"
#include "inc/lexer.h"
#include "inc/util.h"
#include "inc/vars.h"
#include "inc/enc.h"
#include "inc/math.h"
#include "inc/md5.h"
#include "inc/network.h"
#include "inc/search.h"
#include "inc/inset.h"
// For compression!
#include "lz78/wrapper.h"

#define strtok_next(s) strtok_r (NULL, s, &strtok_save)

char *process_line (char *line)
{
    char *strtok_save;
    char *tok_srch, *retbuf, *filebuf, *compbuf, *loopbuf;
    //printf("%s", &line[strlen(line)-2]);
    static char pathbuf[MAXPATHLENGTH+1];
    // Needed for strncpy
    static char line_backup[MAXPATHLENGTH+1];

    bzero(line_backup, sizeof(line_backup));
    strcpy(line_backup, line);

    // Check to see if we're dealing with a 
    // variable (for the end if the lexer)
    int isVar = check_for_var(line);
    tok_srch = strtok_r (line, "=\" ;", &strtok_save);

    /* reuse function */
    /*else if (strncmp("temp",tok_srch,4) == 0)
    {
        tok_srch = strtok_next (" ");
    }*/

    /* if line starts with a comment, skip */
    if (strncmp("#",tok_srch,1) == 0)
    {
        return NULL;
    }

    if(strncmp("\n", tok_srch,1) == 0)
    {
        return NULL;
    }
    char **func_args = line_to_args(parse_vars(line_backup));

    // Check for main calls from user in interactive
    if (strncmp("exit", tok_srch, 4) == 0)
        x_error("ss:exit called");

    else if (strncmp("version", tok_srch, 7) == 0)
    {
        x_warn(":ss:version: %s, type 'help' for function list\n", VERSION);
        return NULL;
    }

    else if (strncmp("help", tok_srch, 4) == 0)
    {
        x_warn(":ss:help:\n%s", FUNCTION_HELP);
        return NULL;

    /*    if(strncmp("read", tok_srch[5], 4) == 0)
        {

        }
        else if()
        {

        }*/
    }

    // Lets add if and loop statements, make this
    // Somewhat usable as a language in other instances

    // If statement, processes string if first arg is true
    else if (strncmp("if:", tok_srch, 3) == 0)
    {
        char *proc_return;
        char *dobuf;

        // We have an if statement
        tok_srch = strtok_next (";");

        if (tok_srch == NULL)
        {
            x_warn("ss:warn:if statement requires a compare argument");
            return NULL;
        }

        // Check if there's anything after the first quote
        if (strcmp(tok_srch, "\n") == 0  ||
           strcmp(tok_srch, " \n") == 0 ||
           strcmp(tok_srch, " ") == 0)
        {
            x_warn("ss:warn:if syntax error, missing function call(s)?");
            return NULL;
        }

        compbuf = qmalloc(QM_SS, (strlen(tok_srch) + 1));
        *compbuf = '\0';
        strcat(compbuf, tok_srch);

        tok_srch = strtok_next (";");

        if ((strncmp ("true" ,
                parse_vars (parse_bq (compbuf)), 4) == 0) ||
            (strncmp ("1"    ,
                parse_vars (parse_bq (compbuf)), 1) == 0))

        {
            while (tok_srch != NULL)
            {
                dobuf  = qmalloc (QM_SS, (strlen (tok_srch) + 1));
                *dobuf = '\0';
                strcat (dobuf, tok_srch);
                proc_return = process_line (parse_vars (dobuf));

                if (proc_return != NULL)
                {
                    printf ("%s\n", proc_return);
                    fflush (stdout);
                }

                tok_srch = strtok_next (";");
            }
        }

        return NULL;

    }

//@@@
    else if (strncmp("ifn:", tok_srch, 4) == 0)
    {
        char *proc_return;
        char *dobuf;

        // We have an if statement
        tok_srch = strtok_next (";");

        if (tok_srch == NULL)
        {
            x_warn("ss:warn:ifn statement requires a compare argument.");
            return NULL;
        }

        // Check if there's anything after the first quote

        if (strcmp(tok_srch, "\n") == 0  ||
            strcmp(tok_srch, " \n") == 0 ||
            strcmp(tok_srch, " ") == 0)
        {
            x_warn("ss:warn:ifn syntax error, missing function call(s)?");
            return NULL;
        }

        compbuf  = qmalloc(QM_SS, (strlen(tok_srch) + 1));
        *compbuf = '\0';

        strcat (compbuf, tok_srch);

        tok_srch = strtok_next (";");

        if ((strncmp ("false" ,
                parse_vars (parse_bq (compbuf)), 5) == 0) ||
            (strncmp ("0"     ,
                parse_vars (parse_bq (compbuf)), 1) == 0))

        {
            while (tok_srch != NULL)
            {
                dobuf  = qmalloc (QM_SS, (strlen (tok_srch) + 1));
                *dobuf = '\0';
                strcat (dobuf, tok_srch);
                proc_return = process_line (parse_vars (dobuf));

                if (proc_return != NULL)
                {
                    printf ("%s\n", proc_return);
                    fflush (stdout);
                }

                tok_srch = strtok_next (";");
            }
        }

        return NULL;
    }

    // Loop
    else if (strncmp("loop:", tok_srch, 5) == 0)
    {
        int loop_count, ii;
        char *proc_return;
        char *countbuf;

        // We have an if statement
        tok_srch = strtok_next (";");

        if (tok_srch == NULL)
        {
            x_warn("ss:warn:loop statement requires arguments");
            return NULL;
        }

        // Check if there's anything after the first quote
        if (strcmp(tok_srch, "\n") == 0  ||
           strcmp(tok_srch, " \n") == 0 ||
           strcmp(tok_srch, " ") == 0)
        {
            x_warn("ss:warn:loop syntax error, missing argument?");
            return NULL;
        }

        countbuf = qmalloc(QM_SS, (strlen(parse_vars(tok_srch)) + 1));
        *countbuf = '\0';
        strcat(countbuf, parse_vars(tok_srch));
        loop_count = atoi(countbuf);

        tok_srch = strtok_next (";");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:loop syntax error, missing function call?");
            return NULL;
        }

        loopbuf  = qmalloc (QM_SS, (strlen (tok_srch) + 1));
        *loopbuf = '\0';
        strcat (loopbuf, tok_srch);

        for(ii = 0; ii < loop_count; ii++)
        {
            proc_return = process_line (parse_vars (loopbuf));

            if (proc_return != NULL)
            {
                printf ("%s\n", proc_return);
                fflush (stdout);
            }

            tok_srch = strtok_next (";");
        }

        return NULL;
    }

    // IF statement
    else if (strncmp("comp:", tok_srch, 5) == 0)
    {
        // We have an if statement
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:if statement requires arguments");
            return NULL;
        }

        // Check if there's anything after the first quote
        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:if syntax error, missing first argument?");
            return NULL;
        }

        // Make sure the end quote exists
        if (strtok_next ("\"") == NULL)
        {
           x_warn("ss:warn:if syntax error, missing quote?");
           return NULL;
        }

        compbuf = qmalloc(QM_SS, (strlen(parse_vars(tok_srch)) + 1));
        strcpy(compbuf, parse_vars(tok_srch));

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:if statement requires two compared arguments");
            return NULL;
        }

        // Check if there's anything after the first quote
        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:if syntax error, missing second argument?");
            return NULL;
        }

        // Make sure the end quote exists
        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:if syntax error, missing end quote?");
            return NULL;
        }

        if (atoi(compbuf) == atoi(parse_vars(tok_srch)) &&
           strncmp(compbuf, parse_vars(tok_srch), strlen(compbuf)) == 0)
        {
            return "true";
        }
        else
        {
            return "false";
        }
    }

    // Unset variable function
    else if (strncmp("unset", tok_srch, 5) == 0)
    {
        char *varname;

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:unset syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:unset syntax error, missing end quote?");
            return NULL;
        }

        varname = clear_var_data(tok_srch);

        return varname;
    }

    // Change directory
    else if (strncmp("backdir", tok_srch, 7) == 0)
    {
        int chdir_return = chdir("..");
        if (chdir_return < 0)
        {
            x_warn("ss:warn:backdir, failed to move directory location");
        }
    }

    // Move files using rename()
    else if (strncmp("move",tok_srch,4) == 0)
    {
        char orig_fn[MAX_STRING_BUFSIZE]; // Should never be more than 6 characters
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:move syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:move syntax error, missing filename?");
            return NULL;
        }

        if (strlen(parse_vars(tok_srch)) < MAX_STRING_LEN)
        {
            strcpy(orig_fn, parse_vars(tok_srch));
        }
        else
        {
            x_warn("ss:warn:move syntax error, missing first filename?");
            return NULL;
        }

        /* strtok to the content that will be written to file */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:move syntax error, missing quote?");
            return NULL;
        }

        tok_srch = strtok_next ("\"");
        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:move syntax error, missing second filename?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:move syntax error, missing quote?");
            return NULL;
        }

        int rename_return = rename(orig_fn, parse_vars(tok_srch));
        if (rename_return < 0)
        {
            x_warn("ss:warn:move, failed to move file");
        }

        return NULL;
    }


    // Show current directory.
    else if (strncmp("showpath", tok_srch, 8) == 0)
    {
        // Get current directory, if it errors, return NULL
        if (getcwd(pathbuf, sizeof(pathbuf)) == NULL) {
            return NULL;
        }
        // All good, return path
        return pathbuf;
    }

    // Change directory
    else if (strncmp("chdir", tok_srch, 5) == 0 || strncmp("cd", tok_srch, 2) == 0)
    {
        char *dirname;
        int chdir_return;

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:chdir syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:chdir syntax error, missing end quote?");
            return NULL;
        }

        dirname = parse_vars(tok_srch);

        chdir_return = chdir(dirname);

        if (chdir_return < 0)
        {
            x_warn("ss:warn:chdir, error changing directory");
        }
        return NULL;
    }

    // Print directory
    else if (strncmp("showdir", tok_srch, 7) == 0)
    {
        char *dirname;

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            dirname = ".";
        }

        if (strtok_next ("\"")==NULL && dirname == NULL)
        {
            x_warn("ss:warn:showdir syntax error, missing end quote?");
            return NULL;
        }

        if (dirname == NULL)
            dirname = parse_vars(tok_srch);

        struct dirent **files;
        int nn, dirstr_size;

        nn = scandir (dirname, &files, NULL, alphasort);

        if (nn < 0)
        {
            x_warn("ss:warn:showdir, failed to open directory");
            return NULL;
        }

        dirstr_size = 14;

        for (int jj = 0; jj < nn; jj++)
        {
            struct dirent *ent = files [jj];
            dirstr_size += (strlen(ent->d_name)+3);
        }

        retbuf = qmalloc(QM_SS, dirstr_size);

        sprintf(retbuf, "%s", "");

        for (int ii = 0; ii < nn; ii++)
        {
            struct dirent *ent = files [ii];
            strcat(retbuf, ent->d_name);
            strcat(retbuf, "\n");
        }

        for (int ii = 0; ii < nn; ii++) { free (files [ii]); }
        free (files);

        return retbuf;
    }

    /* COMPRESSION AND DECOMPRESSION */
    else if (strncmp("decompress",tok_srch,10) == 0)
    {
        char *filename, *decomp_filename;
        int lzret;
        wrapper *lzwrapper;
        int bsize = B_SIZE_DEFAULT;
        uint8_t w_mode = WRAPPER_MODE_DECOMPRESS;
        uint8_t w_type = LZ78_ALGORITHM;

        retbuf = qmalloc(QM_SS, 8129);

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:decompress syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:decompress syntax error, missing end quote?");
            return NULL;
        }

        filename = parse_vars(tok_srch);
        decomp_filename = remove_extension(parse_vars(tok_srch));

        if (bsize <= 0) {
            x_warn("ss:warn:decompress, default buffer not set?");
            return NULL;
        }

        /* Creates a wrapper instance */
        lzwrapper = wrapper_new(w_mode, w_type, NULL);
        if (lzwrapper == NULL) {
            x_warn("ss:warn:decompress, failed to open lz78 wrapper socket!");
            return NULL;
        }

        /* Executes the wrapper function */
        lzret = wrapper_exec(lzwrapper, filename, decomp_filename);

        if (lzret != WRAPPER_SUCCESS)
        {
            x_warn("ss:warn:decompress, failed to decompress tarball: %d", lzret);
            return NULL;
        }
        else
        {
            sprintf(retbuf, "Decompressed -> %s", decomp_filename);
        }

        /* Destroyes the wrapper instance */
        wrapper_destroy(lzwrapper);

        return retbuf;

    }

    /* Compression function of tar */
    else if (strncmp("compress",tok_srch,8) == 0)
    {
        char filename[MAX_FILENAME_LEN+1];
        char cfilename[MAX_FILENAME_LEN+4];
        int lzret;
        wrapper *lzwrapper;
        int bsize = B_SIZE_DEFAULT;
        uint8_t w_mode = WRAPPER_MODE_COMPRESS;
        uint8_t w_type = LZ78_ALGORITHM;

        retbuf = qmalloc(QM_SS, 8129);

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:compress syntax error, missing quote?");
            return NULL;
        }

        // Save tarball filename
        if (strlen(parse_vars(tok_srch)+3) < MAX_FILENAME_LEN)
        {
            sprintf(filename, "%s", parse_vars(tok_srch));
            sprintf(cfilename, "%s.lz", filename);
        }
        else
        {
            x_warn("ss:warn:compress, filename too long!");
            return NULL;
        }

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:compress syntax error, missing quote?");
            return NULL;
        }

        if (bsize <= 0) {
            x_warn("ss:warn:compress, default buffer not set?");
            return NULL;
        }

        /* Creates a wrapper instance */
        lzwrapper = wrapper_new(w_mode, w_type, NULL);
        if (lzwrapper == NULL) {
            x_warn("ss:warn:compress, failed to open lz78 wrapper socket!");
            return NULL;
        }

        /* Executes the wrapper function */
        lzret = wrapper_exec(lzwrapper, filename, cfilename);
    
        if (lzret != WRAPPER_SUCCESS)
        {
            x_warn("ss:warn:compress, error on compress: %d", lzret);
            return NULL;
        }
        else
        {
            sprintf(retbuf, "Compressed -> %s.lz", filename);
        }

        /* Destroyes the wrapper instance */
        wrapper_destroy(lzwrapper);

        return retbuf;
    }

    /* mkdir function, and mkfile functions */
    else if (strncmp("mkdir",tok_srch,5) == 0)
    {
        int parsed;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:mkdir syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"")==NULL)
        {
            x_warn("ss:warn:mkdir syntax error, missing end quote?");
            return NULL;
        }

        parsed = file_exists(parse_vars(tok_srch));
        if (parsed == 1)
        {
            x_warn("ss:warn:mkdir, file exists");
            return NULL;
        }

        // Create directory if need pe
        int mkpret = mkpath(parse_vars(tok_srch), 0755);

        if (mkpret == -1)
            x_warn("ss:warn:mkdir, failed to make directory");

        return NULL;
    }

    else if (strncmp("mkfile",tok_srch,5) == 0)
    {
        int parsed;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:mkfile syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"")==NULL)
        {
            x_warn("ss:warn:mkfile syntax error, missing end quote?");
            return NULL;
        }

        parsed = file_exists(parse_vars(tok_srch));
        if (parsed == 1)
        {
            x_warn("ss:warn:mkfile, file exists");
            return NULL;
        }

        // Create directory if need pe
        int mkpret = mkpath(parse_vars(tok_srch), 0755);

        if (mkpret == -1)
            x_warn("ss:warn:mkfile, failed to form parent path, attempting to write file.");

        FILE *cfile = fopen(parse_vars(tok_srch), "w");
        if (cfile == NULL)
        {
            x_warn("ss:warn:mkfile, failed to open file");
            return NULL;
        }

        fprintf(cfile, "%d", '\0');
        fclose(cfile);
        return NULL;
    }


    /* time function */
    else if (strncmp("time",tok_srch,4) == 0)
    {
        char *parsed;
        parsed = ss_time();
        return strip_nl(parsed);
    }

    /* isfile function */
    else if (strncmp("isfile",tok_srch,5) == 0)
    {
        int parsed;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:isfile syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"")==NULL)
        {
            x_warn("ss:warn:isfile syntax error, missing end quote?");
            return NULL;
        }

        parsed = file_exists(parse_vars(tok_srch));
        if (parsed == 1)
        {
            return "1";
        }
        else
        {
            return "0";
        }
    }

    /* isdir function */
    else if (strncmp("isdir",tok_srch,5) == 0)
    {
        int parsed;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:isdir syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"")==NULL)
        {
            x_warn("ss:warn:isdir syntax error, missing end quote?");
            return NULL;
        }

        parsed = is_dir(parse_vars(tok_srch));
        if (parsed < 1)
        {
            return "0";
        }
        else
        {
            return "1";
        }
    }

    /* print function */
    else if (strncmp("print",tok_srch,5) == 0)
    {
        char *parsed;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:print syntax error, missing quote?");
            return NULL;
        }

        parsed = parse_vars(tok_srch);
        if (parsed != NULL)
        {
            return parsed;
        }
        else
        {
            x_warn("ss:warn:print compulation error, no argument?");
            return NULL;
        }
    }

    /* sleep function */
    else if (strncmp("sleep",tok_srch,5) == 0)
    {
        tok_srch = strtok_next (" ");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:sleep syntax error, need trailing integer for operation");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0  || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:sleep syntax error, need trailing integer for operation");
            return NULL;
        }

        /* if there is a new line, remove it */
        if (tok_srch[strlen(tok_srch)-1] == '\n')
        {
           tok_srch[strlen(tok_srch)-1] = 0;
        }
        sleep(atoi(parse_vars(tok_srch)));
        return NULL;
    }

    // Calc function, some math involved! //
    else if (strncmp("calc",tok_srch,5) == 0)
    {
        char *expr_return;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:calc syntax error, missing quotes around equation");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0  || (strcmp(tok_srch, " \n") == 0))
        {
            x_warn("ss:warn:calc syntax error, missing equation?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:calc syntax error, missing ending quote?");
            return NULL;
        }

        expr_return = ss_expr(parse_vars(tok_srch));

        return expr_return;
    }

    /* Networking, listen */
    else if (strncmp("netlisten",tok_srch,9) == 0)
    {
        char port[7]; // Should never be more than 6 characters
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:netlisten syntax error, missing beginning quote");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:netlisten syntax error, missing address?");
            return NULL;
        }

        if (strlen(parse_vars(tok_srch)) < 7)
        {
            strcpy(port, parse_vars(tok_srch));
        }
        else
        {
            x_warn("ss:warn:netlisten syntax error, port too long?");
            return NULL;
        }

        /* strtok to the content that will be written to file */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:netlisten syntax error, missing end quote?");
            return NULL;
        }

        snet_listen(atoi(port));
        return NULL;
    }

    /* Networking, listen */
    else if (strncmp("nethttp",tok_srch,7) == 0)
    {
        char port[7]; // Should never be more than 6 characters
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:nethttp syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:nethttp syntax error, missing port value?");
            return NULL;
        }

        if (strlen(parse_vars(tok_srch)) < 7)
        {
            strcpy(port, parse_vars(tok_srch));
        }
        else
        {
            x_warn("ss:warn:nethttp syntax error, missing quote?");
            return NULL;
        }

        /* strtok to the content that will be written to file */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:nethttp syntax error, missing quote?");
            return NULL;
        }


        tok_srch = strtok_next ("\"");
        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:nethttp syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:nethttp syntax error, missing quote?");
            return NULL;
        }

        if (atoi(parse_vars(tok_srch)) == 1 || atoi(parse_vars(tok_srch)) == 0)
        {
            snet_http(atoi(port), atoi(parse_vars(tok_srch)));
        }
        else
        {
            x_warn("ss:warn:nethttp syntax error, fork = 1, not 0");
            return NULL;
        }


        return NULL;
    }

    /* Networking, connect */
    else if (strncmp("nettoss",tok_srch,10) == 0)
    {
        char address[MAX_ADDRESS_BUF];
        char data[MAX_STRING_BUFSIZE];
        char port[7];
        /* strtok to filename of function */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:nettoss syntax error, missing quote?");
            return NULL;
        }


        /* Check to see if syntax is correct */
        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:nettoss syntax error, missig address?");
            return NULL;
        }

        /* open file */
        strcpy(address, parse_vars(tok_srch));

        /* strtok to the content that will be written to file */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:nettoss syntax error, missing quote?");
            return NULL;
        }

        tok_srch = strtok_next ("\"");
        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:nettoss syntax error, missing quote?");
            return NULL;
        }

        if (strlen(parse_vars(tok_srch)) > 6)
        {
            x_warn("ss:warn:nettoss syntax error, port too long");
            return NULL;
        }

        strcpy(port, parse_vars(tok_srch));

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:nettoss syntax error, missing quote?");
            return NULL;
        }

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:nettoss syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:nettoss syntax error, send string");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:nettoss syntax error, missing end quote?");
            return NULL;
        }

        strcpy(data, parse_vars(tok_srch));

        snet_toss(address, atoi(port), data);
        return NULL;
    }

    /* ss encrypt function */
    else if (strncmp("encode", tok_srch,6) == 0)
    {
        char *var_conv;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:encode syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:encode syntax error, encode string?");
            return NULL;
        }


        var_conv = parse_vars(tok_srch);
        if (var_conv != NULL)
        {
            char *encrp;
            encrp = ss_encrypt(var_conv);
            return encrp;
        }
        else
        {
            x_warn("ss:warn:encode returned NULL!");
            return NULL;
        }

    }

    /* ss decrypt function */
    else if (strncmp("decode", tok_srch,6) == 0)
    {
        char *var_conv;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:decode syntax error, missing quote?");
            return NULL;
        }


        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:decode syntax error, missing decode data?");
            return NULL;
        }

        var_conv = parse_vars(tok_srch);
        if (var_conv != NULL)
        {
            char *decrp;
            decrp = ss_decrypt(var_conv);
            return decrp;
        }
        else
        {
            x_warn("ss:warn:decode returned NULL!");
            return NULL;
        }
    }

    /* builtin md5 function */
    else if (strncmp("md5",tok_srch,3) == 0)
    {
        char *file_line, *catfile, *file_md5_val;

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:md5 syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:md5 syntax error, need filename");
            return NULL;
        }

        file_line = parse_vars(tok_srch);
        file_md5_val = md5_file(file_line);
        catfile = ss_concat(file_md5_val, file_line);

        return catfile;
    }

    else if (strncmp("search",tok_srch,6) == 0)
    {
        char filename[MAX_FILENAME_BUFSIZE];
        char *search_str, *retval;
        FILE* search_file = NULL;
        /* strtok to filename of function */

        bzero(filename, MAX_FILENAME_LEN);

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:search syntax error, missing quote?");
            return NULL;
        }

        /* Check to see if syntax is correct */
        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:search syntax error, missing filename");
            return NULL;
        }

        /* open file */
        if (MAX_FILENAME_LEN < atoi(parse_vars(tok_srch)))
        {
            x_warn("ss:warn:search, filename too long");
            return NULL;
        }

        strcat(filename, parse_vars(tok_srch));
        search_file = fopen(filename, "r");
        /* Check if file exists and can be opened */
        if (search_file == NULL)
        {
            x_warn("ss:warn:search, failed to open file");
            return NULL;
        }

        /* strtok to the content that will be written to file */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            fclose(search_file);
            x_warn("ss:warn:search syntax error, missing quote?");
            return NULL;
        }

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            fclose(search_file);
            x_warn("ss:warn:search syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            fclose(search_file);
            x_warn("ss:warn:search syntax error, missing write data?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            fclose(search_file);
            x_warn("ss:warn:search syntax error, missing end quote?");
            return NULL;
        }

        search_str = parse_vars(tok_srch);
        retval = strip_nl(ss_search(filename, search_file, search_str));
        fclose(search_file);
        return retval;
    } /* search function */


    /* write */
    else if (strncmp("write",tok_srch,5) == 0)
    {
        char *filename;
        char *file_content;
        FILE* write_file = NULL;
        /* strtok to filename of function */

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:write syntax error, missing quote?");
            return NULL;
        }

        /* Check to see if syntax is correct */
        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:write syntax error, missing filename");
            return NULL;
        }

        /* open file */
        filename = parse_vars(tok_srch);
        write_file = fopen(filename, "w");
        /* Check if file exists and can be opened */
        if (write_file == NULL)
        {
            x_warn("ss:warn:write, failed to open file");
            return NULL;
        }

        /* strtok to the content that will be written to file */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            fclose(write_file);
            x_warn("ss:warn:write syntax error, missing quote?");
            return NULL;
        }

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            fclose(write_file);
            x_warn("ss:warn:write syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            fclose(write_file);
            x_warn("ss:warn:write syntax error, missing write data?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            fclose(write_file);
            x_warn("ss:warn:write syntax error, missing end quote?");
            return NULL;
        }

        file_content = parse_vars(tok_srch);
        fprintf(write_file, "%s\n", file_content);
        fclose(write_file);
        return NULL;
    } /* write function */

    /* read function */
    else if (strncmp("read",tok_srch,4) == 0)
    {
        unsigned long read_size;
        char read_line[1024];
        char *filename, *dynfile;
        FILE *read_file = NULL;

        /* strtok to filename of function */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:read syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:read syntax error, missing quote?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:read syntax error, missing quote?");
            return NULL;
        }

        /* Pull any variables out of the file name
            that may be, and BAM, variable fill! */
        filename = parse_vars(tok_srch);

        // WERE LOADING FILES INTO MEMORY NOW!
        /* open file */
        read_file = fopen(filename, "r");

        /* Check if file was opened successfully */
        if (read_file == NULL)
        {
            x_warn("ss:warn:read, failed to open '%s'", filename);
            return NULL;
        }

        fseek(read_file, 0L, SEEK_END);
        read_size = ftell(read_file);
        rewind(read_file);

        dynfile = qmalloc(QM_SS, read_size);

        char *nullbyte = "\0";
        strcpy(dynfile, nullbyte);

        while(fgets(read_line, sizeof(read_line), read_file) != NULL)
        {
            strcat(dynfile, read_line);
        }

        fclose(read_file);

        return strip_nl(dynfile);
    } /* read function */

    /* Cat function, writes to end of file specified */
    else if (strncmp("cat",tok_srch,3) == 0)
    {
        unsigned long read_size;
        char read_line[1024];
        char filename[2048+1], *dynfile;
        FILE *read_file = NULL;

        /* strtok to filename of function */
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:cat syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:cat syntax error, missing filename?");
            return NULL;
        }

        if (strlen(parse_vars(tok_srch)) < 2048)
        {
            strcpy(filename, parse_vars(tok_srch));
        }
        else
        {
            x_warn("ss:warn:cat, filename too long");
            return NULL;
        }

        // WERE LOADING FILES INTO MEMORY NOW!
        /* open file */
        read_file = fopen(filename, "r");

        /* strtok to the content that will be written to file */
        if (read_file == NULL)
        {
            x_warn("ss:warn:cat, failed to open file");
            return NULL;
        }

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            fclose(read_file);
            x_warn("ss:warn:cat syntax error, missing quote?");
            return NULL;
        }

        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            fclose(read_file);
            x_warn("ss:warn:cat syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            fclose(read_file);
            x_warn("ss:warn:cat syntax error, missing write data?");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            fclose(read_file);
            x_warn("ss:warn:cat syntax error, missing end quote?");
            return NULL;
        }

        fseek(read_file, 0L, SEEK_END);
        read_size = ftell(read_file);
        rewind(read_file);

        dynfile = qmalloc(QM_SS, read_size);

        strcpy(dynfile, "\0");

        while(fgets(read_line, sizeof(read_line), read_file) != NULL)
        {
            strcat(dynfile, read_line);
        }

        fclose(read_file);

        filebuf = qmalloc(QM_SS, (read_size + strlen(parse_vars(tok_srch))));
        read_file = fopen(filename, "w");
        sprintf(filebuf, "%s%s", dynfile, parse_vars(tok_srch));
        fprintf(read_file, "%s", filebuf);
        fclose(read_file);
        return NULL;
    } /* cat function */

    else if (strncmp("delete", tok_srch, 6) == 0) {
        char *del_filename;
        tok_srch = strtok_next ("\"");
        if (tok_srch == NULL)
        {
            x_warn("ss:warn:delete syntax error, missing quote?");
            return NULL;
        }

        if (strcmp(tok_srch, "\n") == 0 || strcmp(tok_srch, " \n") == 0)
        {
            x_warn("ss:warn:delete syntax error, missing filename");
            return NULL;
        }

        if (strtok_next ("\"") == NULL)
        {
            x_warn("ss:warn:delete syntax error, missing quote?");
            return NULL;
        }

        /* Pull variables out of filename if any */
        del_filename = parse_vars(tok_srch);
        if (access(del_filename, F_OK) == 0)
        {
            if (access(del_filename, W_OK) == 0)
            {
                remove(del_filename);
                return NULL;
            }
            else
            {
                x_warn("ss:warn:delete, file not accessible");
                return NULL;
            }

        }
        else
        {
            x_warn("ss:warn:delete, file not found");
            return NULL;
        }
    }

    // Set variables if needed.
    else if (strcmp(tok_srch, "\n") != 0 && strcmp(tok_srch, "") != 0)
    {
        if(isVar == 1)
        {
            int varc = get_var_count();
            char *varname_tmp = tok_srch;
            char *bq_check;
            tok_srch = strtok_next ("=");

            // Check for back quotes, return string with backquotes processed
            bq_check = strip_nl(parse_vars(parse_bq(tok_srch)));
            // Don't check if variable is blank, if so let it fly!
            set_var(varc, varname_tmp, bq_check);
            printf("ss: var '%s' -> %s\n", varname_tmp, get_var_data(varname_tmp));
        }
        else
        {

            // Make SS a shell as well :)
            ss_exec(func_args);

            free(func_args);
        }
    }

    return NULL;
}
